package jude.java.util;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.Writer;
import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.util.Collection;

import jude.java.money.spring.ContextHolder;

import org.apache.commons.lang.StringUtils;
import org.hibernate.FlushMode;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.orm.hibernate3.SessionFactoryUtils;
import org.springframework.orm.hibernate3.SessionHolder;
import org.springframework.transaction.support.TransactionSynchronizationManager;

public class Utils {
	private static final String CONFIG_TPL_PATH = "E:\\Workspaces\\php\\money\\config\\";
	
	public static void startSystem(String dbname) {
//		try {
//			renderConfiguration(dbname);		//生成文件后需要编译
//		} catch (IOException e) {
//			e.printStackTrace();
//		}
		String db = "main";
		if (StringUtils.isNotEmpty(dbname))
			db = dbname;
		ApplicationContext context = new ClassPathXmlApplicationContext(
				new String[] { "/applicationContext-"+db+".xml" });
		SessionFactory sessionFactory = (SessionFactory) context.getBean("sessionFactory");
		Session session = SessionFactoryUtils.getSession(sessionFactory, true);
		session.setFlushMode(FlushMode.AUTO);	//NEVER
		TransactionSynchronizationManager.bindResource(sessionFactory,
				new SessionHolder(session));
		ContextHolder.setApplicationContext(context);
	}
	public static void startSystem() {
		startSystem(null);
	}
	
	public static void closeSystem() {
		ApplicationContext context = ContextHolder.getApplicationContext();
		if (context instanceof ConfigurableApplicationContext) {
			((ConfigurableApplicationContext)context).close();
		}
	}
	
	static void renderConfiguration(String dbname) throws IOException {
		Reader reader = new InputStreamReader(new FileInputStream(CONFIG_TPL_PATH + "config.properties.tpl"), "UTF-8");
		StringBuilder sb = new StringBuilder();
		char[] buff = new char[1024];
		int n;
		while ((n = reader.read(buff, 0, buff.length)) > 0) {
			sb.append(buff, 0, n);
		}
		reader.close();
		Writer writer = new FileWriter(CONFIG_TPL_PATH + "config.properties");
		String c = sb.toString();
		if (StringUtils.isEmpty(dbname))
			dbname = "money";
		c = StringUtils.replace(c, "{DB_NAME}", dbname);
		c = StringUtils.replace(c, "{USERNAME}", "root");
		c = StringUtils.replace(c, "{PASSWORD}", "jude");
		writer.write(c);
		writer.close();
	}

	public static int getInteger(Object str, int def) {
		try {
			if (str instanceof Float)
				return ((Float)str).intValue();
			else if (str instanceof Long)
				return ((Long)str).intValue();
			return Integer.parseInt(String.valueOf(str), 10);
		} catch (NumberFormatException e) {
		}
		return def;
	}
	public static long getLong(String str, long def) {
		try {
			return Long.parseLong(str, 10);
		} catch (NumberFormatException e) {
		}
		return def;
	}
	
	/** 系统中所有金钱相关存储以分为单位, 转换为元为单位显示 */
	public static String toPrice(int num) {
		if (num % 100 == 0)
			return String.valueOf(num / 100);
		if (num % 10 == 0) {
			return (num / 10) + "." + (num % 10);
		}
		return (num / 100) + "." + (num % 100);
	}
	
	/** 输入的价格(单位为元)转为数据库存储的数值(单位为分) */
	public static int toPrice(String price) {
		try {
			float v = Float.parseFloat(price);
			BigDecimal bd = new BigDecimal(v * 100).setScale(0, BigDecimal.ROUND_FLOOR);
			return bd.intValue();
		} catch (NumberFormatException e) {
		}
		return 0;
	}
	
	public static String toPrecision(double num, int precision) {
		BigDecimal bd = new BigDecimal(num).setScale(precision, BigDecimal.ROUND_HALF_UP);
		return bd.toString();
	}
	
	public static void sleep(long ms) {
		try {
			if (ms > 0)
				Thread.sleep(ms);
		} catch (InterruptedException e) {
		}
	}
	
	public static String toString(Throwable e) {
		if (e == null)
			return null;
		StringBuilder sb = new StringBuilder();
		sb.append(e.getClass().getName()).append(":");
		StackTraceElement trace = e.getStackTrace()[0];
		sb.append(trace.getLineNumber()).append("@").append(trace.getFileName());
		sb.append("#").append(trace.getMethodName());
		return sb.toString();
	}
	
	public static boolean toContinue() {
		System.out.println("press y|Y to continue, press n|N to break.");
		while (true) {
			try {
				int i = System.in.available();
				if (i > 0) {
					System.in.read(new byte[i]);
				}
				char c = (char)System.in.read();
				if (c == 'y' || c == 'Y')
					return true;
				if (c == 'n' || c == 'N')
					return false;
			} catch (IOException e) {
			}
		}
	}
	
	public static String toTime(long ms) {
		return toTime((int)(ms / 1000));
	}
	
	public static String toTime(int second) {
		if (second < 100)
			return second + "s";
		if (second < 360)
			return second / 60 + "m " + second % 60 + "s";
		if (second < 3600)
			return second / 60 + "m";
		return second / 3600 + "h " + second % 3600 / 60 + "m";
	}
	
	public static int readChar() {
		try {
			int i = System.in.available();
			if (i > 0) {
				System.in.read(new byte[i]);
			}
		} catch (Exception e) {
		}
		while (true) {
			try {
				return System.in.read() & 0xffffffff;
			} catch (Exception e) {
			}
		}
//		return 0;
	}
	
	public static String readCommand() {
		try {
			int i = System.in.available();
			if (i > 0) {
				System.in.read(new byte[i]);
			}
			BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
			return reader.readLine();
		} catch (Exception e) {
		}
		return null;
	}
	
	/**
	 * min -> max-1
	 * */
	public static int random(int min, int max) {
		if (max < min) {
			int t = max;
			max = min;
			min = t;
		}
		java.util.Random r = new java.util.Random();
		return r.nextInt(max - min) + min;
	}

	/**
	 * 0 -> max-1
	 */
	public static int random(int max) {
		return random(0, max);
	}
	
	public static boolean inScript(String html, int position) {
		if (html == null || position < 0)
			return false;
		int scriptStart = html.indexOf("<script", position);
		int scriptEnd = html.indexOf("</script>", position);
		if (scriptEnd >= 0 && (scriptStart == -1 || scriptStart > scriptEnd) && html.indexOf("<script") < position)
			return true;
		return false;
	}
	
	public static int size(Object o) {
		if (o == null)
			return 0;
		if (o instanceof Collection<?>)
			return ((Collection<?>)o).size();
		if (o.getClass().isArray())
			return Array.getLength(o);
		return 0;
	}

	public static boolean isEmpty(Collection<?> c) {
		return c == null || c.isEmpty();
	}
	
	public static boolean isEmpty(Object o) {
		if (o == null)
			return true;
		if (o.getClass().isArray())
			return Array.getLength(o) == 0;
		else if (o instanceof Collection)
			return ((Collection<?>)o).isEmpty();
		else if (o instanceof String)
			return ((String)o).isEmpty();
		return false;
	}
	
	
	public static String wrapLeft(String original, String prefix) {
		if (original != null && prefix != null && !original.startsWith(prefix))
			return prefix + original;
		return original;
	}
	
	public static String wrapRight(String original, String subfix) {
		if (original != null && subfix != null && !original.endsWith(subfix))
			return original + subfix;
		return original;
	}

	public static String wrap(String original, String wrap) {
		return wrapRight(wrapLeft(original, wrap), wrap);
	}

	public static boolean in(String str, String[] array) {
		for (int i = 0; i < array.length; i++) {
			if (array[i].equals(str))
				return true;
		}
		return false;
	}
}
